資料科學與推廣教育的愛好者,台大商研所畢,創辦 DataInPoint 致力為資料科學愛好者提供最棒的教學資源。任職過上海的外商新創團隊、台北的外商軟體公司與民營銀行,閒暇時喜歡長跑與乒乓球。
folium 視覺化get_tidy_df¶https://github.com/yaojenkuo/cec-2018/blob/master/tidy_election_data.py
from tidy_election_data import get_tidy_df
city_ids = [100, 200, 300, 400, 500, 600]
county_ids = list(range(701, 715)) + [801, 802]
cities = ["台北市", "新北市", "桃園市", "台中市", "台南市", "高雄市"]
counties = ["新竹縣", "苗栗縣", "彰化縣", "南投縣", "雲林縣", "嘉義縣", "屏東縣", "宜蘭縣", "花蓮縣", "台東縣", "澎湖縣", "基隆市", "新竹市", "嘉義市", "金門縣", "連江縣"]
admin_areas = cities + counties
city_xls_file_urls = ["https://s3-ap-northeast-1.amazonaws.com/tw-election-2018/city-mayor/{}.xls".format(cid) for cid in city_ids]
county_xls_file_urls = ["https://s3-ap-northeast-1.amazonaws.com/tw-election-2018/county-mayor/{}.xls".format(cid) for cid in county_ids]
xls_file_urls = city_xls_file_urls + county_xls_file_urls
df_dict = dict()
for file_url, admin_area in zip(xls_file_urls, admin_areas):
tidy_df = get_tidy_df(file_url)
long_df = tidy_df[1]
long_df.insert(0, "admin_area", admin_area)
df_dict[admin_area] = long_df
候選人人數:5 候選人姓名: 1 無黨籍 吳蕚洋 2 中國國民黨 丁守中 3 民主進步黨 姚文智 4 無黨籍 柯文哲 5 無黨籍 李錫錕 資料框的列數為:1563,投票所個數為:1563 候選人人數:2 候選人姓名: 1 民主進步黨 蘇貞昌 2 中國國民黨 侯友宜 資料框的列數為:2446,投票所個數為:2446 候選人人數:5 候選人姓名: 1 無黨籍 朱梅雪 2 中國國民黨 陳學聖 3 無黨籍 楊麗環 4 無黨籍 吳富彤 5 民主進步黨 鄭文燦 資料框的列數為:1142,投票所個數為:1142 候選人人數:3 候選人姓名: 1 無黨籍 宋原通 2 民主進步黨 林佳龍 3 中國國民黨 盧秀燕 資料框的列數為:1601,投票所個數為:1601 候選人人數:6 候選人姓名: 1 民主進步黨 黃偉哲 2 中國國民黨 高思博 3 無黨籍 林義豐 4 無黨籍 許忠信 5 無黨籍 陳永和 6 無黨籍 蘇煥智 資料框的列數為:1322,投票所個數為:1322 候選人人數:4 候選人姓名: 1 中國國民黨 韓國瑜 2 民主進步黨 陳其邁 3 無黨籍 璩美鳳 4 無黨籍 蘇盈貴 資料框的列數為:1823,投票所個數為:1823 候選人人數:4 候選人姓名: 1 中國國民黨 楊文科 2 無黨籍 葉芳棟 3 民主進步黨 鄭朝方 4 民國黨 徐欣瑩 資料框的列數為:404,投票所個數為:404 候選人人數:4 候選人姓名: 1 無黨籍 朱泰平 2 無黨籍 徐定禎 3 無黨籍 黃玉燕 4 中國國民黨 徐耀昌 資料框的列數為:470,投票所個數為:470 候選人人數:5 候選人姓名: 1 民主進步黨 魏明谷 2 中國國民黨 王惠美 3 無黨籍 白雅燦 4 無黨籍 黃文玲 5 無黨籍 洪敏雄 資料框的列數為:1049,投票所個數為:1049 候選人人數:2 候選人姓名: 1 中國國民黨 林明溱 2 民主進步黨 洪國浩 資料框的列數為:488,投票所個數為:488 候選人人數:4 候選人姓名: 1 無黨籍 林佳瑜 2 民主進步黨 李進勇 3 無黨籍 王麗萍 4 中國國民黨 張麗善 資料框的列數為:557,投票所個數為:557 候選人人數:4 候選人姓名: 1 民主進步黨 翁章梁 2 無黨籍 吳芳銘 3 無黨籍 林國龍 4 中國國民黨 吳育仁 資料框的列數為:486,投票所個數為:486 候選人人數:3 候選人姓名: 1 無黨籍 李鎔任 2 中國國民黨 蘇清泉 3 民主進步黨 潘孟安 資料框的列數為:689,投票所個數為:689 候選人人數:5 候選人姓名: 1 無黨籍 林信華 2 中國國民黨 林姿妙 3 民主進步黨 陳歐珀 4 無黨籍 林錦坤 5 無黨籍 陳秋境 資料框的列數為:399,投票所個數為:399 候選人人數:3 候選人姓名: 1 中國國民黨 徐榛蔚 2 民主進步黨 劉曉玫 3 無黨籍 黄師鵬 資料框的列數為:299,投票所個數為:299 候選人人數:5 候選人姓名: 1 無黨籍 鄺麗貞 2 民主進步黨 劉櫂豪 3 無黨籍 黃裕斌 4 無黨籍 彭權國 5 中國國民黨 饒慶鈴 資料框的列數為:213,投票所個數為:213 候選人人數:7 候選人姓名: 1 無黨籍 翁珍聖 2 無黨籍 鄭清發 3 無黨籍 陳大松 4 無黨籍 吳政隆 5 中國國民黨 賴峰偉 6 民主進步黨 陳光復 7 無黨籍 呂華苑 資料框的列數為:116,投票所個數為:116 候選人人數:2 候選人姓名: 1 中國國民黨 謝立功 2 民主進步黨 林右昌 資料框的列數為:257,投票所個數為:257 候選人人數:6 候選人姓名: 1 無黨籍 謝文進 2 無黨籍 李驥羣 3 無黨籍 黃源甫 4 中國國民黨 許明財 5 無黨籍 郭榮睿 6 民主進步黨 林智堅 資料框的列數為:299,投票所個數為:299 候選人人數:4 候選人姓名: 1 無黨籍 蕭淑麗 2 中國國民黨 黃敏惠 3 無黨籍 黃宏成台灣阿成世界偉人財神總統 4 民主進步黨 涂醒哲 資料框的列數為:177,投票所個數為:177 候選人人數:6 候選人姓名: 1 中國國民黨 楊鎮浯 2 金門高粱黨 洪志恒 3 教科文預算保障e聯盟 汪承樺 4 無黨籍 陳福海 5 無黨籍 謝宜璋 6 無黨籍 洪和成 資料框的列數為:78,投票所個數為:78 候選人人數:4 候選人姓名: 1 樹黨 蘇柏豪 2 無黨籍 朱秀珍 3 無黨籍 魏耀乾 4 中國國民黨 劉增應 資料框的列數為:9,投票所個數為:9
import pandas as pd
mayors = pd.DataFrame()
for k in df_dict:
mayors = mayors.append(df_dict[k], ignore_index=True)
print(mayors.shape)
mayors.head()
mayors.to_csv("mayors.csv", index=False)
(62689, 8)
from google.colab import files
!ls
files.download("mayors.csv")
pandas 讀入¶import pandas as pd
mayors = pd.read_csv("https://s3-ap-northeast-1.amazonaws.com/tw-election-2018/mayors.csv")
print(mayors.shape)
(62689, 8)
mayors.head()
| admin_area | district | village | office | number | party | candidate | votes | |
|---|---|---|---|---|---|---|---|---|
| 0 | 台北市 | 北投區 | 建民里 | 1 | 1 | 無黨籍 | 吳蕚洋 | 4 |
| 1 | 台北市 | 北投區 | 建民里 | 2 | 1 | 無黨籍 | 吳蕚洋 | 2 |
| 2 | 台北市 | 北投區 | 建民里 | 3 | 1 | 無黨籍 | 吳蕚洋 | 2 |
| 3 | 台北市 | 北投區 | 文林里 | 4 | 1 | 無黨籍 | 吳蕚洋 | 1 |
| 4 | 台北市 | 北投區 | 文林里 | 5 | 1 | 無黨籍 | 吳蕚洋 | 5 |
mayors.tail()
| admin_area | district | village | office | number | party | candidate | votes | |
|---|---|---|---|---|---|---|---|---|
| 62684 | 連江縣 | 北竿鄉 | 后沃村、橋仔村、塘岐村 | 5 | 4 | 中國國民黨 | 劉增應 | 838 |
| 62685 | 連江縣 | 北竿鄉 | 坂里村、白沙村、芹壁村 | 6 | 4 | 中國國民黨 | 劉增應 | 301 |
| 62686 | 連江縣 | 莒光鄉 | 田沃村、西坵村、青帆村 | 7 | 4 | 中國國民黨 | 劉增應 | 341 |
| 62687 | 連江縣 | 莒光鄉 | 大坪村、福正村 | 8 | 4 | 中國國民黨 | 劉增應 | 391 |
| 62688 | 連江縣 | 東引鄉 | 樂華村、中柳村 | 9 | 4 | 中國國民黨 | 劉增應 | 396 |
mayors.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 62689 entries, 0 to 62688 Data columns (total 8 columns): admin_area 62689 non-null object district 62689 non-null object village 62689 non-null object office 62689 non-null int64 number 62689 non-null int64 party 62689 non-null object candidate 62689 non-null object votes 62689 non-null int64 dtypes: int64(3), object(5) memory usage: 3.8+ MB
matplotlib.pyplotpandasseabornbokehplotly / dashfoliummatplotlib.pyplot¶pandas¶seaborn¶folium¶matplotlib.pyplot¶import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
myfont = FontProperties(fname="/System/Library/Fonts/STHeiti Light.ttc")
tp = mayors[mayors["admin_area"] == "台北市"]
grouped = tp.groupby(["number", "candidate"])
ttl_votes = pd.DataFrame(grouped["votes"].sum()).reset_index()
ttl_votes
| number | candidate | votes | |
|---|---|---|---|
| 0 | 1 | 吳蕚洋 | 5617 |
| 1 | 2 | 丁守中 | 577566 |
| 2 | 3 | 姚文智 | 244641 |
| 3 | 4 | 柯文哲 | 580820 |
| 4 | 5 | 李錫錕 | 6172 |
plt.barh(y=ttl_votes["number"].values, width=ttl_votes["votes"].values)
plt.yticks(ttl_votes["number"].values, ttl_votes["candidate"].values, fontproperties=myfont)
plt.title("台北市長得票數", fontproperties=myfont)
plt.show()
pandas¶import pandas as pd
tp = mayors[mayors["admin_area"] == "台北市"]
grouped = tp.groupby(["number", "candidate"])
ttl_votes = pd.DataFrame(grouped["votes"].sum()).reset_index()
ttl_votes
| number | candidate | votes | |
|---|---|---|---|
| 0 | 1 | 吳蕚洋 | 5617 |
| 1 | 2 | 丁守中 | 577566 |
| 2 | 3 | 姚文智 | 244641 |
| 3 | 4 | 柯文哲 | 580820 |
| 4 | 5 | 李錫錕 | 6172 |
ax = ttl_votes.plot(x="candidate", y="votes", kind="barh")
ax.set_yticklabels(ttl_votes['candidate'], fontproperties=myfont)
plt.show()
seaborn¶import pandas as pd
import seaborn as sns
tp = mayors[mayors["admin_area"] == "台北市"]
grouped = tp.groupby(["number", "candidate"])
ttl_votes = pd.DataFrame(grouped["votes"].sum()).reset_index()
ttl_votes
| number | candidate | votes | |
|---|---|---|---|
| 0 | 1 | 吳蕚洋 | 5617 |
| 1 | 2 | 丁守中 | 577566 |
| 2 | 3 | 姚文智 | 244641 |
| 3 | 4 | 柯文哲 | 580820 |
| 4 | 5 | 李錫錕 | 6172 |
sns.barplot(x="votes", y="number", data=ttl_votes, orient="h", ci=None)
plt.show()
import pandas as pd
import seaborn as sns
city_names = {
"台北市": "Taipei",
"新北市": "New Taipei",
"桃園市": "Taoyuan",
"台中市": "Taichung",
"台南市": "Tainan",
"高雄市": "Kaohsiung"
}
cities = mayors[mayors["admin_area"].isin(["台北市", "新北市", "桃園市", "台中市", "台南市", "高雄市"])]
grouped = cities.groupby(["admin_area", "number"])
ttl_votes = pd.DataFrame(grouped["votes"].sum()).reset_index()
ttl_votes["admin_area_en"] = ttl_votes["admin_area"].map(city_names)
ttl_votes
| admin_area | number | votes | admin_area_en | |
|---|---|---|---|---|
| 0 | 台中市 | 1 | 15919 | Taichung |
| 1 | 台中市 | 2 | 619855 | Taichung |
| 2 | 台中市 | 3 | 827996 | Taichung |
| 3 | 台北市 | 1 | 5617 | Taipei |
| 4 | 台北市 | 2 | 577566 | Taipei |
| 5 | 台北市 | 3 | 244641 | Taipei |
| 6 | 台北市 | 4 | 580820 | Taipei |
| 7 | 台北市 | 5 | 6172 | Taipei |
| 8 | 台南市 | 1 | 367518 | Tainan |
| 9 | 台南市 | 2 | 312874 | Tainan |
| 10 | 台南市 | 3 | 84153 | Tainan |
| 11 | 台南市 | 4 | 45168 | Tainan |
| 12 | 台南市 | 5 | 117179 | Tainan |
| 13 | 台南市 | 6 | 39778 | Tainan |
| 14 | 新北市 | 1 | 873692 | New Taipei |
| 15 | 新北市 | 2 | 1165130 | New Taipei |
| 16 | 桃園市 | 1 | 18200 | Taoyuan |
| 17 | 桃園市 | 2 | 407234 | Taoyuan |
| 18 | 桃園市 | 3 | 51518 | Taoyuan |
| 19 | 桃園市 | 4 | 3867 | Taoyuan |
| 20 | 桃園市 | 5 | 552330 | Taoyuan |
| 21 | 高雄市 | 1 | 892545 | Kaohsiung |
| 22 | 高雄市 | 2 | 742239 | Kaohsiung |
| 23 | 高雄市 | 3 | 7998 | Kaohsiung |
| 24 | 高雄市 | 4 | 14125 | Kaohsiung |
g = sns.FacetGrid(ttl_votes, col="admin_area_en", col_wrap=3)
g = sns.FacetGrid(ttl_votes, col="admin_area_en", col_wrap=3, sharey=False, sharex=False, col_order=["Taipei", "New Taipei", "Taoyuan", "Taichung", "Tainan", "Kaohsiung"])
g.map(sns.barplot, "votes", "number", orient="h", order=None)
plt.show()
folium 視覺化¶pip install --upgrade folium
#conda install folium -c conda-forge
!pip install --upgrade folium
import folium
m = folium.Map(location=[25.0389, 121.5682], zoom_start=15)
m
import folium
marker_loc = [25.0389, 121.5682]
tooltip = 'Click!'
m = folium.Map(location=marker_loc, zoom_start=15)
folium.Marker(marker_loc, popup='台灣亞馬遜網路服務有限公司', tooltip=tooltip).add_to(m)
<folium.map.Marker at 0x117eef5f8>
m
import requests
geojson = "https://s3-ap-northeast-1.amazonaws.com/tw-election-2018/twCounty2010.geo.json"
r = requests.get(geojson)
geojson_as_dict = r.json()
print(geojson_as_dict.keys())
dict_keys(['type', 'features'])
for i in range(len(geojson_as_dict["features"])):
print(geojson_as_dict["features"][i]["properties"])
{'COUNTYSN': '10014001', 'COUNTYNAME': '台東縣', 'name': '台東縣'}
{'COUNTYSN': '10002001', 'COUNTYNAME': '宜蘭縣', 'name': '宜蘭縣'}
{'COUNTYSN': '63000001', 'COUNTYNAME': '台北市', 'name': '台北市'}
{'COUNTYSN': '10009001', 'COUNTYNAME': '雲林縣', 'name': '雲林縣'}
{'COUNTYSN': '10003001', 'COUNTYNAME': '桃園縣', 'name': '桃園縣'}
{'COUNTYSN': '10013001', 'COUNTYNAME': '屏東縣', 'name': '屏東縣'}
{'COUNTYSN': '10006001', 'COUNTYNAME': '台中市', 'name': '台中市'}
{'COUNTYSN': '10011001', 'COUNTYNAME': '台南市', 'name': '台南市'}
{'COUNTYSN': '10017001', 'COUNTYNAME': '基隆市', 'name': '基隆市'}
{'COUNTYSN': '09007001', 'COUNTYNAME': '連江縣', 'name': '連江縣'}
{'COUNTYSN': '10008001', 'COUNTYNAME': '南投縣', 'name': '南投縣'}
{'COUNTYSN': '10016001', 'COUNTYNAME': '澎湖縣', 'name': '澎湖縣'}
{'COUNTYSN': '10005001', 'COUNTYNAME': '苗栗縣', 'name': '苗栗縣'}
{'COUNTYSN': '10020001', 'COUNTYNAME': '嘉義市', 'name': '嘉義市'}
{'COUNTYSN': '10004001', 'COUNTYNAME': '新竹縣', 'name': '新竹縣'}
{'COUNTYSN': '10001001', 'COUNTYNAME': '新北市', 'name': '新北市'}
{'COUNTYSN': '10015001', 'COUNTYNAME': '花蓮縣', 'name': '花蓮縣'}
{'COUNTYSN': '10012001', 'COUNTYNAME': '高雄市', 'name': '高雄市'}
{'COUNTYSN': '10007001', 'COUNTYNAME': '彰化縣', 'name': '彰化縣'}
{'COUNTYSN': '10010001', 'COUNTYNAME': '嘉義縣', 'name': '嘉義縣'}
{'COUNTYSN': '09020001', 'COUNTYNAME': '金門縣', 'name': '金門縣'}
{'COUNTYSN': '10018001', 'COUNTYNAME': '新竹市', 'name': '新竹市'}
import folium
m = folium.Map(location=[24, 121], zoom_start=7, tiles='Mapbox Bright')
geojson = "twCounty2010.geo.json"
folium.GeoJson(
geojson,
name="geojson"
).add_to(m)
folium.LayerControl().add_to(m)
<folium.map.LayerControl at 0x117d1e400>
m